package com.hr;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.espirit.eap.manager.DepartmentService;
import com.espirit.eap.sa.Employee;
import com.espirit.eap.sa.EmployeeService;
import com.espirit.eap.util.DateUtils;
import com.espirit.eap.util.StatGenericJPAService;
import com.googlecode.cswish.annotation.ParamScope;
import com.googlecode.cswish.model.PageElements;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.model.ParameterMap;
import com.googlecode.cswish.model.Reference;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.SearchCallback;

@Service
public class DutyRecordService {
	private static final Log logger = LogFactory
			.getLog(DutyRecordService.class);

	@Resource
	StatGenericJPAService genericService;
	
	@Resource
	DepartmentService departmentService;
	
	@Resource
	EmployeeService employeeService;
	
	@PersistenceContext(unitName="espirit")
	protected EntityManager em;
	
	public  PageInfo search(final ParameterMap model, int start, int limit,
    		String sort, String dir, boolean newSearch, Reference<QLInfo> qlInfoRef,
    		@ParamScope(visible=false, value="#ps")PageElements ps ,boolean fromMenu
    		) {
		
		SearchCallback callback = departmentService.buildDeptDefaultSearchCallback(model, null, null);
		return genericService.search(model, start, limit, sort, dir, newSearch, qlInfoRef, callback, true, false);
	}
	
	//TODO
	private BigDecimal getFaultAmounts(Employee emp, Integer year, Integer month) {
		return null;
	}

	private Integer getDeliveryTimes(Employee emp, Integer year, Integer month) {
		return 0;
	}

	public List<DutyRecord> getEmployeeDutyRecords(Employee emp, Date timeFrom, Date timeTo, Integer state) {
		String hql = String.format("from " + DutyRecord.class.getName() + " a where a.dutyTime between '%s' and '%s' AND a.employee.id = %s", 
				DateUtils.format(timeFrom, "yyyy-MM-dd HH:mm:ss"), DateUtils.format(timeTo, "yyyy-MM-dd HH:mm:ss"), emp.getId()
				);
		
		if (state != null) {
			hql += " AND a.state = " + state ;
		}
		QLInfo qlInfo = new QLInfo(hql, true);
		List<DutyRecord> dutyRecords = genericService.searchByQl(qlInfo, false).getData();
		return dutyRecords;
	}

	public List<DutyRecord> getEmployeeDutyRecordsByType(Employee emp, Date timeFrom, Date timeTo, Integer type) {
		String hql = String.format("from " + DutyRecord.class.getName() + " a where a.dutyTime between '%s' and '%s' and a.employee.id = %s", 
				DateUtils.format(timeFrom, "yyyy-MM-dd HH:mm:ss"), DateUtils.format(timeTo, "yyyy-MM-dd HH:mm:ss"), emp.getId()
				);
		
		if (type != null) {
			hql += " and a.type = " + type ;
		}
		QLInfo qlInfo = new QLInfo(hql, true);
		List<DutyRecord> dutyRecords = genericService.searchByQl(qlInfo, false).getData();
		return dutyRecords;
	}
	
	
	public boolean delteDutyRecord(Employee emp, Date timeFrom, Date timeTo, Integer state) {
		List<DutyRecord> dutyRecords = getEmployeeDutyRecords(emp, timeFrom, timeTo, state);
		
		for (DutyRecord dutyRecord : dutyRecords) {
			genericService.delete(dutyRecord);
		}
		return true;
	}
	
	public void saveForgetDuty(DutyRecord dr) {
		String hql = String.format("from " + DutyRecord.class.getName() + " a where a.dutyTime = '%s' and a.type = %s and a.employee.id = %s", 
				DateUtils.format(dr.getDutyTime(), "yyyy-MM-dd HH:mm:ss"), DutyRecord.TYPE_FORGET, dr.getEmployee().getId()
				);
		QLInfo qlInfo = new QLInfo(hql, true);
		List<DutyRecord> dutys = genericService.searchByQl(qlInfo, false).getData();
		if (dutys.isEmpty()) {
			genericService.add(dr);
		}
	}
	
	
	@Transactional
	public void importFile(DutyRecordImport model){
		List<Object> updateModels = genericService.convertFileToModelList(model);
		employeeService.cleanEmployeeDutyCardCach(); // if user  change dutycard of employee, should sync record
		
		int itemCount = 0;
		for (Object object : updateModels){
			DutyRecord dutyRecord = (DutyRecord)object;
			if (dutyRecord == null) continue;
			if (dutyRecord.getEmployee() == null){
				if (dutyRecord.getUserId() == null) continue;
				
				String userId = dutyRecord.getUserId().trim();
				String empId = employeeService.getEmployeeIdByUserId(userId);
//				logger.debug("user id:" + userId);
				
				if (empId == null) continue;
				
//				logger.debug("emp id:" + empId);
				
				Employee emp = genericService.load(Employee.class, empId);
				if (emp == null) continue;
				
				dutyRecord.setEmployee(emp);
			
			}
			dutyRecord.setType(DutyRecord.TYPE_NORMAL);
			genericService.add(dutyRecord);
			
			logger.debug("emp id:" + dutyRecord.getEmployee().getName());
			if (++itemCount % 100 == 0){
				em.flush();
				em.clear();
			}
		}
	}
	
}